#include <stdio.h>
#include <stdlib.h>
#include <time.h>

/*	matrix_multiplication.cpp
*	This program is part of the °Simple-Benchs° Benchmark
*	The complexity of this program is O(n³) where n is the Matrix's size
*
*	
*	To run the program:	./program rows columns max_num
*/


/* Array initialization. Complexity O(n²) where n is the matrix's size*/
void initArray(int **vet, int rows, int columns, int max_num) {
  int count, count2;
  for (count = 0; count < rows; count++) {
    vet[count] = (int*) malloc(columns * sizeof(int));
    for (count2 = 0; count2 < columns; count2++) {
      vet[count][count2] = rand() % max_num;
    }
  }
}

/* Program standart output. Display a Matrix.  Complexity O(n²) where n is the matrix's size */
void printArray(int **vet, int rows, int columns) {
  int count, count2;
  for (count = 0; count < rows; count++) {
    for (count2=0; count2 < columns; count2++) {
      printf("%8d", vet[count][count2]);
    }
    printf("\n");
  }
  printf("\n");
}

/*	Perform the Matrix multiplication. Complexity O(n³) defined by the nested loops starting the line 46, 
where n is the number of rows/columns in the input square matrix */
int** multiply(int **matA, int **matB, int rows, int columns) {
  int count, count2, count3, sum;
  int **result = (int**)calloc(rows,sizeof(int*));

  for (count = 0; count < rows; count++)
    result[count] = (int*)calloc(columns,sizeof(int));

  for (count=0; count < rows; count++) {
    for(count2=0; count2 < columns; count2++) {
      sum = 0;
      for(count3=0; count3 < rows; count3++) {
        sum += matA[count][count3] * matB[count3][count2];
      }
      result[count][count2] = sum;
    }
  }
  return result;
}

/*	Initial check to verify whether the amount of arguments is correct or not.  Complexity O(1)	*/
short Initial_check(int inputs){
  if (inputs != 3) {
    fprintf(stderr, "Wrong number of argments. Syntax: ./program matrix_size max_num\n");
    return 1;
  }
  return 0;
}

/*	Auxiliar function to free all blocks in heap. Complexity O(n) where n is the amount of rows in the square matrix */
void free_all(int **matA, int **matB, int **matC, int size){
  int count;
  for (count = 0; count < size; count++){
    free(matA[count]);
    free(matB[count]);
    free(matC[count]);
  }
  free(matA);
  free(matB);
  free(matC);
}


int main(int argc, char** argv) {

	/* Checking arguments */
  if (Initial_check(argc)) return 1;

  /* Retrieve problem size. */
  int rows = atoi(argv[1]);
  //int columns = atoi(argv[2]);
  int columns = rows;
  int max_num = atoi(argv[3]);

  /* Seed initialization. */
 	srand((unsigned)time(NULL));

	/* Variable declaration/allocation/initialization. */
  int **matA = (int**) malloc(rows * sizeof(int*));
  int **matB = (int**) malloc(rows * sizeof(int*));  
  initArray(matA, rows, columns, max_num);
  initArray(matB, rows, columns, max_num);

  /*	Computing the multiplication*/
  int **result = multiply(matA, matB, rows, columns);

  /* Display the result*/  	
  printArray(matA, rows, columns);
  printArray(matB, rows, columns);
  printArray(result, rows, columns);

  /* Be clean. */
  free_all(matA,matB,result,rows);
  return 0;
}
